﻿// ==================================================================================================
// Copyright(C) 2012 NCS Pte. Ltd. All rights reserved.
//
// SYSTEM NAME	    : iConnect .Net Application Framework
// COMPONENT ID	    : NCS.IConnect.Architecture.Client
// COMPONENT DESC   : The foundation component of the whole framework. 	
//
// CREATED DATE/BY  : 13 Apr 2012 / Wu Yong Qing
//
// REVISION HISTORY :	
// DATE/BY			SR#/CS/PM#/OTHERS		DESCRIPTION OF CHANGE
// ==================================================================================================

using Microsoft.Practices.Unity.InterceptionExtension;
using NCS.IConnect.Core.Wcf;
using System;
using System.Collections.Generic;
using System.ServiceModel;
using Microsoft.Practices.EnterpriseLibrary.ExceptionHandling;

namespace NCS.IConnect.Core.IoC.TransientCall
{
    /// <summary>
    /// Channel exception handling behavior.
    /// </summary>
    public class ChannelExceptionHandlingBehavior : IInterceptionBehavior
    {
        #region Implementation of IInterceptionBehavior

        /// <summary>
        /// Invokes the specified input.
        /// </summary>
        /// <param name="input">The input.</param>
        /// <param name="getNext">The get next.</param>
        /// <returns>Instance of <see cref="IMethodReturn"/></returns>
        public IMethodReturn Invoke(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext)
        {
            IMethodReturn result = null;
            ICommunicationObject channel = null;
            result = getNext().Invoke(input, getNext);

            var instanceProviderAware = input.Target as IInstanceProviderAware;
            if (instanceProviderAware != null)
            {
                channel = instanceProviderAware.InstanceProvider.Current as ICommunicationObject;
            }

            if (result.Exception != null)
            {
                if (channel != null)
                {
                    channel.Abort();
                    channel.Close();
                }
                Guid handingInstanceId;
                Exception exception = FaultExceptionHelper.Handle(result.Exception, out handingInstanceId);
                if (handingInstanceId != Guid.Empty)
                {
                    HandlingInstanceIdUtil.AddId(exception, handingInstanceId);
                }
                return input.CreateExceptionMethodReturn(exception);
            }

            if (channel != null)
            {
                channel.Close();
            }

            return result;
        }

        /// <summary>
        /// Gets the required interfaces.
        /// </summary>
        /// <returns>Required interface type sequences</returns>
        public IEnumerable<Type> GetRequiredInterfaces()
        {
            return Type.EmptyTypes;
        }

        /// <summary>
        /// Gets a value indicating whether [will execute].
        /// </summary>
        /// <value>
        ///   <c>true</c> if [will execute]; otherwise, <c>false</c>.
        /// </value>
        public bool WillExecute
        {
            get
            {
                return true;
            }
        }

        #endregion
    }
}
